(in-package :leam)

(defclass test-leam-stream-handler()())

(defmethod on-handle-data((handler test-leam-stream-handler) msg-id msg-stream)
  (let ((msg (make-array (get-remaining msg-stream) :fill-pointer 0
			 :element-type 'standard-char)))
    (loop for index from 0 to (- (get-remaining msg-stream) 1) do
	  (vector-push (code-char (read-unsigned-8 msg-stream)) msg))
    (format t "Recieved message ~S~%"
	    msg)))

(defmethod on-handle-ack((handler test-leam-stream-handler) msg-id)
  (format t "Message ~S acknowledged~%" msg-id))

(defmethod on-handle-fin((handler test-leam-stream-handler) msg-id)
  (format t "Message ~S finished~%" msg-id))

(defmethod on-handle-error ((handler test-leam-stream-handler)
			    msg-id stack-trace data-stream)
  (format t "Message ~S error, stack-trace ~S~%" msg-id stack-trace))

(defmethod on-handle-close((handler test-leam-stream-handler))
  (format t "Connection closed"))

(defvar *test-stream-systems* nil
  "List of all stream handlers")

(defun make-test-socket-handler( disconnector stream id )
  (handler-case 
      (let* ((leam-handler (make-instance 'test-leam-stream-handler))
	     (leam-stream (make-leam-stream stream stream leam-handler))
	     (read-handler (lambda ()
			     (read-next leam-stream)))
	     (eof-handler (lambda(fd-handler-handle)
			    (format t "~s disconnected~%" id)
			    (funcall disconnector)
			    (sb-impl::remove-fd-handler fd-handler-handle)
			    (remove leam-stream *test-stream-systems*))))
	(format t "~s connected ~%" id)
	(push leam-stream *test-stream-systems*)
	(values read-handler eof-handler))
    (end-of-file()
      (format t "Failed to initialize stream, eof detected~%"))))

(defun write-leam-message(leam-stream message)
  (multiple-value-bind
	(msg-id out-stream)
      (begin-send-message leam-stream (length message))
    (format t "Sending message ~s, id ~s~%" message msg-id)
    (loop for index from 0 to (- (length message) 1) do
	  (write-unsigned-8 out-stream (char-int (aref message index))))))

(defun start-test-leam-server()
  (let ((port 7000))
    (create-stream-server port #'make-test-socket-handler)))

(export 'start-test-leam-server)
